#include <sys/queue.h>
#include "pthread.hpp"
#include "lockguard.hpp"
#include <queue>
#include <pthread.h>
#include <vector>
#include <unistd.h>
// 引入自行封装的线程创建
#define NUM 5
class Task
{
public:
    Task()
    {
        ;
    }
    Task(int x, int y, char op)
        : _x(x), _y(y), _op(op)
    {
        ;
    }
    void operator()()
    {
        switch (_op)
        {
        case '+':
        {
            _result = _x + _y;
            _exitcode = 0;
        }
        break;
        case '-':
        {
            _result = _x - _y;
            _exitcode = 0;
        }
        break;
        case '*':
        {
            _result = _x * _y;
            _exitcode = 0;
        }
        break;
        case '/':
        {
            if (_y == 0)
                _exitcode = 1;
            else
                _result = _x / _y;
        }
        break;
        case '%':
        {
            if (_y == 0)
                _exitcode = 1;
            else
                _result = _x % _y;
        }
        break;
        }
    }
    std::string getformat()
    {
        return std::to_string(_x) + _op + std::to_string(_y) + '?';
    }
    std::string getRformat()
    {
        return std::to_string(_result) + "(" + std::to_string(_exitcode) + ")";
    }
    int _x;
    int _y;
    char _op;
    int _result;
    int _exitcode = 0;
};
template <class T>
class threadPool
{
public:
    threadPool(int size = NUM) // vp_存的自定义类型要有默认构造,不然这里初始化会找不到默认构造!
        : vp_(size)
    {
        pthread_mutex_init(&mutex_, nullptr);
        pthread_cond_init(&Consumer, nullptr);
        pthread_cond_init(&Productor, nullptr);
    }
    void init()
    {
        for (int i = 0; i < NUM; i++)
        {
            vp_[i] = (Thread(i, threadRun, this));
        }
    }
    void Lock()
    {
        pthread_mutex_lock(&mutex_);
    }
    void Unlock()
    {
        pthread_mutex_unlock(&mutex_);
    }
    static void *threadRun(void *arg)
    {
        // pthread_detach(pthread_self());
        threadPool<T> *tp = static_cast<threadPool<T> *>(arg);
        // 执行任务
        while (true)
        {
            T data;
            tp->pop(data);
            std::cout << data.getformat() << std::endl;
            data();
            std::cout << data.getRformat() << "id: " << pthread_self() << std::endl;
        }
    }
    bool Full()
    {
        return tasks_.size() == NUM;
    }
    bool Empty()
    {
        return tasks_.size() == 0;
    }
    void start()
    {
        // for(int i = 0; i < NUM; i++)//创建多线程
        // {
        //     pthread_create(&vp_[i],nullptr,threadRun,this);
        // }
        for (auto &e : vp_) // 复用Thread Run方法创建线程
        {
            e.Run();
        }
    }
    ~threadPool()
    {
        for (auto &e : vp_) // 复用Thread join方法回收线程
        {
            e.join();
        }
        pthread_mutex_destroy(&mutex_);
        pthread_cond_destroy(&Consumer);
        pthread_cond_destroy(&Productor);
    }
    void push(const T &data)
    {
        // Lock();
        {
            LockGuard lg(&mutex_);
            while (Full())
            {
                pthread_cond_wait(&Productor, &mutex_);
            }
            tasks_.push(data);
        }
        pthread_cond_signal(&Consumer);
        // Unlock();
    }
    void pop(T &data)
    {
        // Lock();
        {
            LockGuard lg(&mutex_);
            // 检查是否有任务
            while (Empty())
            {
                pthread_cond_wait(&Consumer, &mutex_);
            }
            data = tasks_.front();
            tasks_.pop();
        }
        pthread_cond_signal(&Productor);
        // Unlock();
    }
    std::queue<T> tasks_;    // 任务队列
    std::vector<Thread> vp_; // 线程池,不能存指针,内部要解引用访问的
    pthread_mutex_t mutex_;
    pthread_cond_t Consumer;
    pthread_cond_t Productor;
};